# -*- coding: utf-8 -*-
"""
Shopify HMAC验证工具模块
用于验证Shopify OAuth请求和Webhook请求的HMAC签名
"""
import hmac
import hashlib
import logging
import urllib.parse
from typing import List, Dict, Any
from app.conf.config import logger

def verify_hmac(query_params: dict, shared_secret: str, hmac_value: str) -> bool:
    """
    验证Shopify OAuth请求的HMAC签名
    
    Args:
        query_params: 查询参数字典
        shared_secret: Shopify API Secret
        hmac_value: 接收到的HMAC值
    
    Returns:
        bool: HMAC验证是否通过
    """
    try:
        # 复制参数字典并移除hmac和signature字段
        params = {k: v for k, v in query_params.items() if k != 'hmac' and k != 'signature'}
        
        # 按键名排序并构建查询字符串
        sorted_params = sorted(params.items(), key=lambda x: x[0])
        query_string = '&'.join([f"{k}={urllib.parse.quote_plus(str(v))}" for k, v in sorted_params])
        
        # 计算HMAC
        calculated_hmac = hmac.new(
            shared_secret.encode('utf-8'),
            query_string.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()
        
        # 使用时间安全的比较
        is_valid = hmac.compare_digest(calculated_hmac, hmac_value)
        
        if not is_valid:
            logger.warning("HMAC验证失败: 计算的HMAC与接收到的不匹配")
        
        return is_valid
    except Exception as e:
        logger.error(f"验证HMAC时发生错误: {str(e)}")
        return False

def verify_webhook_hmac(headers: dict, body: bytes, shared_secret: str) -> bool:
    """
    验证Shopify Webhook请求的HMAC签名
    
    Args:
        headers: 请求头字典
        body: 请求体字节
        shared_secret: Shopify API Secret
    
    Returns:
        bool: HMAC验证是否通过
    """
    try:
        # 从请求头获取HMAC
        hmac_value = headers.get('X-Shopify-Hmac-Sha256')
        if not hmac_value:
            logger.warning("Webhook HMAC验证失败: 请求头中缺少X-Shopify-Hmac-Sha256")
            return False
        
        # 计算HMAC
        calculated_hmac = hmac.new(
            shared_secret.encode('utf-8'),
            body,
            hashlib.sha256
        ).hexdigest()
        
        # Base64编码的HMAC比较
        import base64
        expected_hmac = base64.b64encode(hashlib.sha256(body).digest()).decode('utf-8')
        calculated_signature = base64.b64encode(
            hmac.new(shared_secret.encode('utf-8'), body, hashlib.sha256).digest()
        ).decode('utf-8')
        
        # 使用时间安全的比较
        is_valid = hmac.compare_digest(calculated_signature, hmac_value)
        
        if not is_valid:
            logger.warning("Webhook HMAC验证失败: 计算的HMAC与接收到的不匹配")
        
        return is_valid
    except Exception as e:
        logger.error(f"验证Webhook HMAC时发生错误: {str(e)}")
        return False

def verify_query_string_hmac(query_string: str, shared_secret: str, provided_hmac: str) -> bool:
    """
    从查询字符串验证HMAC
    用于FastAPI的请求验证
    
    Args:
        query_string: 原始查询字符串
        shared_secret: Shopify API Secret
        provided_hmac: 提供的HMAC值
    
    Returns:
        bool: HMAC验证是否通过
    """
    try:
        # 解析查询字符串
        query_dict = dict(urllib.parse.parse_qsl(query_string))
        
        # 移除hmac参数
        if 'hmac' in query_dict:
            del query_dict['hmac']
        if 'signature' in query_dict:
            del query_dict['signature']
        
        # 按键排序并重建查询字符串
        sorted_items = sorted(query_dict.items())
        sorted_query_string = '&'.join([f"{k}={v}" for k, v in sorted_items])
        
        # 计算HMAC
        calculated_hmac = hmac.new(
            shared_secret.encode('utf-8'),
            sorted_query_string.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()
        
        # 使用时间安全的比较
        return hmac.compare_digest(calculated_hmac, provided_hmac)
    except Exception as e:
        logger.error(f"验证查询字符串HMAC时发生错误: {str(e)}")
        return False